module uart_tx (
    input               clk     ,
    input               rst_n   ,
    input    [7:0]      tx_data ,
    input               tx_start,
    input    [1:0]      sw      ,
    output   reg        tx      ,
    output              tx_done 
);
//奇偶校验位
wire                  tx_check;
//波特率计数器参数
reg     [12:0]        cnt;
reg                   add_cnt;
wire                  end_cnt;

//bit计数器参数
reg     [3:0]         cnt_bit;
wire                  add_cnt_bit;
wire                  end_cnt_bit;

reg     [12:0]        baud;
reg     [10:0]         data;//数据寄存器

always @(*) begin
    case(sw[1:0])
    2'b00:      baud = 5208;          //9600波特率
    2'b01:      baud = 3472;          //14400波特率
    2'b10:      baud = 1302;          //38400波特率
    2'b11:      baud = 434;           //115200波特率
    default:    baud = 5208;           
    endcase
end

//波特率计数器
always @(posedge clk or negedge rst_n) begin 
    if(!rst_n)begin
        cnt <= 0;
    end 
    else if(add_cnt)begin
        if(end_cnt)begin
            cnt <= 0;
        end
        else begin
            cnt <= cnt + 1;
        end
    end
    else begin
        cnt <= cnt;
    end
end

assign end_cnt = add_cnt && (cnt == baud-1)||(cnt_bit == 4'd10 && cnt == ((baud-1)>>1));

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        add_cnt <= 1'b0;
    end
    else if(end_cnt_bit)begin
        add_cnt <= 1'b0;
    end
    else if(tx_start)begin
        add_cnt <= 1'b1;
    end
end


//bit计数器
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt_bit <= 0;
    end
    else if(add_cnt_bit)begin
        if(end_cnt_bit)begin
            cnt_bit <= 0;
        end
        else begin
            cnt_bit <= cnt_bit + 1;
        end
    end
    else begin
        cnt_bit <= cnt_bit;
    end
end

assign add_cnt_bit = end_cnt;
assign end_cnt_bit = add_cnt_bit && cnt_bit == 4'd11-1;

assign tx_check = ~^tx_data;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        data<=11'b11111111111;
    end
    else if(tx_start)begin
        data<={1'b1,tx_check,tx_data,1'b0};           //数据加启示位
    end
    else begin
        data<=data;
    end
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        tx<=1'b1;
    end
    else if(end_cnt)begin
        tx<=data[cnt_bit];
    end
    else if(end_cnt_bit)begin
        tx<=1'b1;
    end
    else begin
        tx<=tx;
    end
end

assign tx_done = end_cnt_bit;
endmodule